package cn.jinjimi.app.reader;

import com.google.gson.reflect.TypeToken;
import cn.jinjimi.base.util.GsonUtils;
import cn.jinjimi.domain.data.dto.ArticleAllListDTO;
import cn.jinjimi.domain.data.dto.ArticleRecommendListDTO;
import cn.jinjimi.domain.ServiceManager;
import cn.jinjimi.domain.store.ReaderStore;
import cn.jinjimi.app.interfaces.ILoadDataListener;
import cn.jinjimi.app.reader.bean.ArticleData;
import cn.jinjimi.app.reader.bean.ArticleFourViewData;
import cn.jinjimi.app.reader.bean.ArticleSearchViewData;
import cn.jinjimi.app.reader.bean.ArticleViewData;
import cn.jinjimi.app.reader.bean.CacheArticleData;
import cn.jinjimi.app.reader.bean.JinjuViewData;
import cn.jinjimi.app.store.DatabaseManager;
import cn.jinjimi.app.store.dao.CacheDao;
import cn.jinjimi.app.store.entity.ArticleEntity;
import cn.jinjimi.app.main.fragment.ReaderArticleListFragment;
import cn.jinjimi.app.main.widget.CommonRV.IViewData;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

import bolts.Continuation;
import bolts.Task;

/**
 * Created by lforxeverc on 2017/4/14.
 */

public class ArticlePresenter<LD extends List<? extends IViewData>> {
    private List<String> cacheReadArticle = new ArrayList<>();
    public static int LIMIT = 10;
    public static int DEFAULT_PAGE = 1;
    final int loadType;
    final ILoadDataListener<LD> mListener;

    public ArticlePresenter(int loadType, ILoadDataListener l) {
        this.loadType = loadType;
        this.mListener = l;
        cacheReadArticle = loadReadedEntity();
    }

    public static class Data {
        List<IViewData> data;
        private boolean hasMore;
        private boolean isSuccess;
        private String errMsg;

        public Data(List<IViewData> data, boolean hasMore, boolean isSuccess, String err) {
            this.data = data;
            this.hasMore = hasMore;
            this.isSuccess = isSuccess;
            this.errMsg = err;
        }
    }

    public void loadData(int page) {
        if (loadType == ReaderArticleListFragment.TYPE_ALL_ARTICLE) {
            loadAllArticleList(page);
        } else {
            loadRecommendArticle(page);
        }
    }

    private void loadRecommendArticle(final int page) {
        Task.callInBackground(new Callable<ArticleRecommendListDTO>() {
            @Override
            public ArticleRecommendListDTO call() throws Exception {
                return ServiceManager.getService(ReaderStore.class).getRecommendArticleList((page - 1) * LIMIT, LIMIT);
            }
        }).continueWith(new Continuation<ArticleRecommendListDTO, Data>() {
            @Override
            public Data then(Task<ArticleRecommendListDTO> task) throws Exception {
                ArticleRecommendListDTO data = task.getResult();
                boolean isSuccess = false;
                boolean hasMore = false;
                String errMsg = "";
                List<IViewData> dataRet = new ArrayList<>();
                if (data.isOk) {
                    isSuccess = true;
                    List<ArticleData> list = data.getDatas();
                    if (list != null && !list.isEmpty()) {
                        hasMore = list.size() == LIMIT;
                        dataRet = parseRecommentData(list);
                    }
                } else {
                    errMsg = data.msg;
                }
                return new Data(dataRet, hasMore, isSuccess, errMsg);
            }
        }).continueWith(new Continuation<Data, Object>() {
            @Override
            public Object then(Task<Data> task) throws Exception {
                Data data = task.getResult();
                if (data != null) {
                    if (data.isSuccess) {
                        mListener.onLoadSuccess(page, (LD) data.data, data.hasMore);
                    } else {
                        mListener.onLoadFail(page, data.errMsg);
                    }
                }
                return null;
            }
        }, Task.UI_THREAD_EXECUTOR);
    }

    public void hasViewArticle(String id) {
        ArticleEntity entity = new ArticleEntity();
        entity.setId(id);
        DatabaseManager.getInstance().getArticleDao().insertOrReplace(entity);
        cacheReadArticle = loadReadedEntity();
    }

    public void cacheData(List<IViewData> data) {
        if (data == null || data.isEmpty()) return;
        List<IViewData> cache = data.subList(0, data.size() >= 10 ? 10 : data.size());
        DatabaseManager.getInstance().getCacheDao().saveCacheData(cache, getCachekey());

    }

    public List<IViewData> getCacheData() {
        List<IViewData> datas = new ArrayList<>();
        String data = DatabaseManager.getInstance().getCacheDao().getCacheData(getCachekey());
        List<IViewData> cacheData = GsonUtils.fromJson(data, new TypeToken<List<CacheArticleData>>() {
        }.getType());
        if (cacheData != null && !cacheData.isEmpty()) {
            int fourArticlePosition = 0;
            for (IViewData d : cacheData) {
                int type = d.getViewType();
                if (type == ReaderHolderFactory.TYPE_ARTICLE) {
                    ArticleViewData article = new ArticleViewData((ArticleData) d);
                    article.setHasRead(cacheReadArticle.contains(article.getId()));
                    datas.add(article);
                } else if (type == ReaderHolderFactory.TYPE_FOUR_ARTICLE) {
                    ArticleFourViewData four = new ArticleFourViewData((ArticleData) d);
                    four.setCurrentPosition(fourArticlePosition);
                    datas.add(four);
                    fourArticlePosition++;
                } else if (type == ReaderHolderFactory.TYPE_SEARCH) {
                    ArticleSearchViewData search = new ArticleSearchViewData();
                    datas.add(search);
                } else if (type == ReaderHolderFactory.TYPE_JINJU) {
                    JinjuViewData jinju = new JinjuViewData((ArticleData) d);
                    datas.add(jinju);
                }
            }
        }
        return datas;
    }

    private String getCachekey() {
        return CacheDao.READERCATEGOR + loadType;
    }


    private void loadAllArticleList(final int page) {

        Task.callInBackground(new Callable<ArticleAllListDTO>() {
            @Override
            public ArticleAllListDTO call() throws Exception {
                return ServiceManager.getService(ReaderStore.class).getAllArticleList(page, LIMIT);
            }
        }).continueWith(new Continuation<ArticleAllListDTO, Data>() {
            @Override
            public Data then(Task<ArticleAllListDTO> task) throws Exception {
                ArticleAllListDTO data = task.getResult();
                boolean isSuccess = false;
                boolean hasMore = false;
                String errMsg = "";
                List<IViewData> dataRet = new ArrayList<>();
                if (data.isOk) {
                    isSuccess = true;
                    List<ArticleData> list = data.getArticles();
                    if (list != null && !list.isEmpty()) {
                        hasMore = list.size() == LIMIT;
                        dataRet = parseAllList(page == DEFAULT_PAGE, list);
                    }
                } else {
                    errMsg = data.msg;
                }
                return new Data(dataRet, hasMore, isSuccess, errMsg);
            }
        }).continueWith(new Continuation<Data, Object>() {
            @Override
            public Object then(Task<Data> task) throws Exception {
                Data data = task.getResult();
                if (data != null) {
                    if (data.isSuccess) {
                        mListener.onLoadSuccess(page, (LD) data.data, data.hasMore);
                    } else {
                        mListener.onLoadFail(page, data.errMsg);
                    }
                }
                return null;
            }
        }, Task.UI_THREAD_EXECUTOR);

    }

    private List<IViewData> parseAllList(boolean isFirstPage, List<ArticleData> data) {
        List<IViewData> retData = new ArrayList<>();
        boolean isEmpty = data == null || data.isEmpty();
        if (isFirstPage) {
            retData.add(new ArticleSearchViewData());
            if (isEmpty) return retData;
            for (int i = 0; i < data.size(); i++) {
                if (i < 4) {
                    ArticleFourViewData d = new ArticleFourViewData(data.get(i));
                    d.setCurrentPosition(i);
                    retData.add(d);
                } else {
                    ArticleViewData vd = new ArticleViewData(data.get(i));
                    vd = mixLocalData(vd);
                    retData.add(vd);
                }
            }
        } else {
            if (isEmpty) return retData;
            for (int i = 0; i < data.size(); i++) {
                ArticleViewData vd = new ArticleViewData(data.get(i));
                vd = mixLocalData(vd);
                retData.add(vd);
            }
        }
        return retData;
    }

    private List<IViewData> parseRecommentData(List<ArticleData> list) {
        List<IViewData> data = new ArrayList<>();
        if (list == null || list.isEmpty())
            return data;
        boolean showRMargin = false;
        for (ArticleData d : list) {
            String type = d.getType();
            if ("article".equals(type)) {
                showRMargin = false;
                ArticleViewData article = new ArticleViewData(d);
                article = mixLocalData(article);
                data.add(article);
            } else if ("logion".equals(type)) {
                JinjuViewData jinju = new JinjuViewData(d);
                jinju.setIsRightItem(showRMargin);
                data.add(jinju);
                showRMargin = !showRMargin;
            }
        }

        return data;
    }

    private ArticleViewData mixLocalData(ArticleViewData data) {
        if (cacheReadArticle != null && !cacheReadArticle.isEmpty()) {
            data.setHasRead(cacheReadArticle.contains(data.getId()));
        }
        return data;
    }

    private List<String> loadReadedEntity() {
        List<String> ids = new ArrayList<>();
        List<ArticleEntity> cache = DatabaseManager.getInstance().getArticleDao().loadAll();
        if (cache == null || cache.isEmpty())
            return ids;
        for (ArticleEntity entity : cache) {
            ids.add(entity.getId());
        }
        return ids;
    }
}
